home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
msdos
/
raytrace
/
pov
/
bin
/
xtras
/
addon3.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-11
|
27KB
|
1,171 lines
/****************************************************************************
*
* ATTENTION!!!
*
* THIS FILE HAS BEEN MODIFIED!!! IT IS NOT PART OF THE OFFICAL
* POV-RAY 2.2 DISTRIBUTION!!!
*
* THIS FILE IS PART OF "FASTER THAN POV-RAY" (VERSION 2.2),
* A SPED-UP VERSION OF POV-RAY 2.2. USE AT YOUR OWN RISK!!!!!!
*
* New files: addon0.c, addon1.c, addon2.c, addon3.c, addon.h
*
* The additional modules were written by Dieter Bayer.
*
* Send comments, suggestions, bugs, ideas ... to:
*
* e-mail: dieter@cip.e-technik.uni-erlangen.de
* CIS: 100255.3074
*
* All changed/added lines are enclosed in #ifdef DB_CODE ... #endif
*
* The vista projection was taken from:
*
* A. Hashimoto, T. Akimoto, K. Mase, and Y. Suenaga,
* "Vista Ray-Tracing: High Speed Ray Tracing Using Perspective
* Projection Image", New Advances in Computer Graphics, Proceedings
* of CG International '89, R. A. Earnshaw, B. Wyvill (Eds.),
* Springer, ..., pp. 549-560
*
* The idea for the light buffer was taken from:
*
* E. Haines and D. Greenberg, "The Light Buffer: A Shadow-Testing
* Accelerator", IEEE CG&A, Vol. 6, No. 9, Sept. 1986, pp. 6-16
*
*****************************************************************************/
/****************************************************************************
* addon3.c
*
* This module was written by Dieter Bayer.
*
* This module contains the functions used to recompute the
* automatically generated bounding boxes and to removed unnecessary
* bounding objects.
*
* 01.04.1994 : Creation
*
* 29.04.1994 : Version 2.0
*
******************************************************************************/
#include <time.h>
#include "frame.h"
#include "vector.h"
#include "povproto.h"
#include "addon.h"
#ifdef DB_CODE
/*****************************************************************************
* external variables
******************************************************************************/
extern FRAME Frame;
extern unsigned int Options, Extended_Options;
extern METHODS Bicubic_Patch_Methods;
extern METHODS Blob_Methods;
extern METHODS Box_Methods;
extern METHODS Cone_Methods;
extern METHODS Csg_Height_Field_Methods;
extern METHODS CSG_Intersection_Methods;
extern METHODS CSG_Merge_Methods;
extern METHODS CSG_Union_Methods;
extern METHODS Disc_Methods;
extern METHODS Ellipsoid_Methods;
extern METHODS Height_Field_Methods;
extern METHODS Light_Source_Methods;
extern METHODS Plane_Methods;
extern METHODS Poly_Methods;
extern METHODS Quadric_Methods;
extern METHODS Smooth_Triangle_Methods;
extern METHODS Sphere_Methods;
extern METHODS Triangle_Methods;
/*****************************************************************************
* static variables
******************************************************************************/
static long int FoundEllipsoid = 0;
static long int FoundCylinder = 0;
static long int FoundCone = 0;
/*****************************************************************************
* static functions
******************************************************************************/
static void Recompute_Bbox PARAMS((OBJECT *Object, long *count));
static void Remove_Bound PARAMS((OBJECT *Object, long *removed));
/*****************************************************************************
*
* FUNCTION : Recompute_BBoxes
*
* ARGUMENTS : none
*
* MODIFIED ARGS : none
*
* RETURN VALUE : none
*
* AUTHOR : Dieter Bayer, May 1994
*
* DESCRIPTION
*
* Recompute all automatically generated bounding slabs.
*
* CHANGES
*
* -
*
******************************************************************************/
void Recompute_Bboxes()
{
long count;
OBJECT *Object;
count = 0;
fprintf(stderr, "Reducing bounding boxes");
Begin_Point();
for (Object = Frame.Objects; Object != NULL; Object = Object->Sibling)
{
if (Object->Methods == &Light_Source_Methods)
Recompute_Bbox(((LIGHT_SOURCE *)Object)->Children, &count);
else
Recompute_Bbox(Object, &count);
}
fprintf(stderr,"(%ld reduced)", count);
End_Point();
}
/*****************************************************************************
*
* FUNCTION : Recompute_BBox
*
* ARGUMENTS : Object - Object
* count - Counter to count reduced bounding boxes
*
* MODIFIED ARGS : count
*
* RETURN VALUE : none
*
* AUTHOR : Dieter Bayer, May 1994
*
* DESCRIPTION
*
* Recompute the bounding box of an object:
*
* - Calculate the bounding box of CSG intersections by
* intersecting the bounding boxes of all children (obsolete?)
*
* - Consider bounding and clipping objects.
*
* CHANGES
*
* -
*
******************************************************************************/
static void Recompute_Bbox(Object, count)
OBJECT *Object;
long *count;
{
int counted, i, j;
DBL Old_Volume, New_Volume, Bounds_Volume, Clip_Volume;
VECTOR Min, Max, P;
OBJECT *Sib;
BBOX New_Bounds, Old_Bounds, Bounds_Bounds, Clip_Bounds;
METHODS *Methods;
HEIGHT_FIELD *Height_Field;
if (Object == NULL)
return;
counted = FALSE;
/* Check for bounds too large
(I want everything to stay inside the largest bounding box) */
Object->Bounds.Lower_Left.x = max(Object->Bounds.Lower_Left.x, -BOUND_HUGE/2);
Object->Bounds.Lower_Left.y = max(Object->Bounds.Lower_Left.y, -BOUND_HUGE/2);
Object->Bounds.Lower_Left.z = max(Object->Bounds.Lower_Left.z, -BOUND_HUGE/2);
Object->Bounds.Lengths.x = min(Object->Bounds.Lengths.x, BOUND_HUGE);
Object->Bounds.Lengths.y = min(Object->Bounds.Lengths.y, BOUND_HUGE);
Object->Bounds.Lengths.z = min(Object->Bounds.Lengths.z, BOUND_HUGE);
/* Init New_Bounds */
New_Bounds.Lower_Left.x =
New_Bounds.Lower_Left.y =
New_Bounds.Lower_Left.z = -BOUND_HUGE/2;
New_Bounds.Lengths.x =
New_Bounds.Lengths.y =
New_Bounds.Lengths.z = BOUND_HUGE;
BOUNDS_VOLUME (New_Volume, New_Bounds);
/* Get Old_Bounds with bounds from current object */
Old_Bounds = Object->Bounds;
BOUNDS_VOLUME (Old_Volume, Old_Bounds);
/* Init Bounds_Bounds with bounds from object's bounding object */
Bounds_Bounds.Lower_Left.x =
Bounds_Bounds.Lower_Left.y =
Bounds_Bounds.Lower_Left.z = -BOUND_HUGE/2;
Bounds_Bounds.Lengths.x =
Bounds_Bounds.Lengths.y =
Bounds_Bounds.Lengths.z = BOUND_HUGE;
if (Object->Bound != NULL)
{
Min.x = Min.y = Min.z = -BOUND_HUGE;
Max.x = Max.y = Max.z = +BOUND_HUGE;
for (Sib = Object->Bound; Sib != NULL; Sib = Sib->Sibling)
{
/*
Recompute_Bbox(Sib, count);
*/
if (!Test_Inverted(Sib))
{
Min.x = max(Min.x, Sib->Bounds.Lower_Left.x);
Min.y = max(Min.y, Sib->Bounds.Lower_Left.y);
Min.z = max(Min.z, Sib->Bounds.Lower_Left.z);
Max.x = min(Max.x, Sib->Bounds.Lower_Left.x + Sib->Bounds.Lengths.x);
Max.y = min(Max.y, Sib->Bounds.Lower_Left.y + Sib->Bounds.Lengths.y);
Max.z = min(Max.z, Sib->Bounds.Lower_Left.z + Sib->Bounds.Lengths.z);
}
}
Bounds_Bounds.Lower_Left = Min;
VSub (Bounds_Bounds.Lengths, Max, Min);
}
BOUNDS_VOLUME (Bounds_Volume, Bounds_Bounds);
/* Init Clip_Bounds with bounds from object's clipping object */
Clip_Bounds.Lower_Left.x =
Clip_Bounds.Lower_Left.y =
Clip_Bounds.Lower_Left.z = -BOUND_HUGE/2;
Clip_Bounds.Lengths.x =
Clip_Bounds.Lengths.y =
Clip_Bounds.Lengths.z = BOUND_HUGE;
if (Object->Clip != NULL)
{
Min.x = Min.y = Min.z = -BOUND_HUGE;
Max.x = Max.y = Max.z = +BOUND_HUGE;
for (Sib = Object->Clip; Sib != NULL; Sib = Sib->Sibling)
{
/*
Recompute_Bbox(Sib, count);
*/
if (!Test_Inverted(Sib))
{
Min.x = max(Min.x, Sib->Bounds.Lower_Left.x);
Min.y = max(Min.y, Sib->Bounds.Lower_Left.y);
Min.z = max(Min.z, Sib->Bounds.Lower_Left.z);
Max.x = min(Max.x, Sib->Bounds.Lower_Left.x + Sib->Bounds.Lengths.x);
Max.y = min(Max.y, Sib->Bounds.Lower_Left.y + Sib->Bounds.Lengths.y);
Max.z = min(Max.z, Sib->Bounds.Lower_Left.z + Sib->Bounds.Lengths.z);
}
}
Clip_Bounds.Lower_Left = Min;
VSub (Clip_Bounds.Lengths, Max, Min);
}
BOUNDS_VOLUME (Clip_Volume, Clip_Bounds);
Methods = Object->Methods;
/* Check for CSG/primitive objects */
if (Object->Type & COMPOUND_OBJECT)
{
if (Methods == &Light_Source_Methods)
{
Recompute_Bbox(((LIGHT_SOURCE *)Object)->Children, count);
}
else
{
/* CSG object */
if (Methods == &CSG_Intersection_Methods)
{
Min.x = Min.y = Min.z = -BOUND_HUGE;
Max.x = Max.y = Max.z = +BOUND_HUGE;
/* Get the bounding box by recursively calculating the children's
bounding boxes. */
for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
{
Recompute_Bbox(Sib, count);
/* Inverted objects must not be considered! */
if (!Test_Inverted(Sib))
{
Min.x = max(Min.x, Sib->Bounds.Lower_Left.x);
Min.y = max(Min.y, Sib->Bounds.Lower_Left.y);
Min.z = max(Min.z, Sib->Bounds.Lower_Left.z);
Max.x = min(Max.x, Sib->Bounds.Lower_Left.x + Sib->Bounds.Lengths.x);
Max.y = min(Max.y, Sib->Bounds.Lower_Left.y + Sib->Bounds.Lengths.y);
Max.z = min(Max.z, Sib->Bounds.Lower_Left.z + Sib->Bounds.Lengths.z);
}
}
}
else
{
Min.x = Min.y = Min.z = +BOUND_HUGE;
Max.x = Max.y = Max.z = -BOUND_HUGE;
/* Get the bounding box by recursively calculating the children's
bounding boxes. */
for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
{
Recompute_Bbox(Sib, count);
Min.x = min(Min.x, Sib->Bounds.Lower_Left.x);
Min.y = min(Min.y, Sib->Bounds.Lower_Left.y);
Min.z = min(Min.z, Sib->Bounds.Lower_Left.z);
Max.x = max(Max.x, Sib->Bounds.Lower_Left.x + Sib->Bounds.Lengths.x);
Max.y = max(Max.y, Sib->Bounds.Lower_Left.y + Sib->Bounds.Lengths.y);
Max.z = max(Max.z, Sib->Bounds.Lower_Left.z + Sib->Bounds.Lengths.z);
}
}
New_Bounds.Lower_Left = Min;
VSub (New_Bounds.Lengths, Max, Min);
BOUNDS_VOLUME(New_Volume, New_Bounds);
}
}
else
{
/* Primitive object*/
/* The bounding box for height fields is not calculated in POV-Ray 2.2 */
if ((Methods == &Height_Field_Methods) ||
(Methods == &Csg_Height_Field_Methods))
{
Height_Field = (HEIGHT_FIELD *)Object;
New_Bounds.Lower_Left = Height_Field->bounding_box->bounds[0];
VSub (New_Bounds.Lengths, Height_Field->bounding_box->bounds[1], Height_Field->bounding_box->bounds[0]);
recompute_bbox(&New_Bounds, Height_Field->Trans);
BOUNDS_VOLUME (New_Volume, New_Bounds);
}
/* The bounding box for bicubic patches is not calculated in POV-Ray 2.2 */
if (Methods == &Bicubic_Patch_Methods)
{
Min.x = Min.y = Min.z = +BOUND_HUGE;
Max.x = Max.y = Max.z = -BOUND_HUGE;
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
P = ((BICUBIC_PATCH *)Object)->Control_Points[i][j];
Min.x = min (Min.x, P.x);
Min.y = min (Min.y, P.y);
Min.z = min (Min.z, P.z);
Max.x = max (Max.x, P.x);
Max.y = max (Max.y, P.y);
Max.z = max (Max.z, P.z);
}
}
New_Bounds.Lower_Left = Min;
VSub (New_Bounds.Lengths, Max, Min);
BOUNDS_VOLUME (New_Volume, New_Bounds);
}
}
/* Check which bounding box fits best */
if ((New_Volume < Old_Volume) && (New_Volume > 0.0))
{
Object->Bounds = New_Bounds;
Old_Volume = New_Volume;
if (!counted)
{
(*count)++;
counted = TRUE;
Print_Point(POINT_MOD);
}
}
if ((Bounds_Volume < Old_Volume) && (Bounds_Volume > 0.0))
{
Object->Bounds = Bounds_Bounds;
Old_Volume = Bounds_Volume;
if (!counted)
{
(*count)++;
counted = TRUE;
Print_Point(POINT_MOD);
}
}
if ((Clip_Volume < Old_Volume) && (Clip_Volume > 0.0))
{
Object->Bounds = Clip_Bounds;
if (!counted)
{
(*count)++;
counted = TRUE;
Print_Point(POINT_MOD);
}
}
}
/*****************************************************************************
*
* FUNCTION : Test_Inverted
*
* ARGUMENTS : Object - Object
*
* MODIFIED ARGS : none
*
* RETURN VALUE : int - TRUE, if object is inverted
*
* AUTHOR : Dieter Bayer, May 1994
*
* DESCRIPTION
*
* Check if an object is inverted.
*
* CHANGES
*
* -
*
******************************************************************************/
int Test_Inverted(Object)
OBJECT *Object;
{
METHODS *methods;
methods = Object->Methods;
if (methods == &Blob_Methods)
return(((BLOB *)Object)->Inverted);
if (methods == &Box_Methods)
return(((BOX *)Object)->Inverted);
if (methods == &Cone_Methods)
return(((CONE *)Object)->Inverted);
if (methods == &Csg_Height_Field_Methods)
return(((HEIGHT_FIELD *)Object)->Inverted);
if (methods == &CSG_Intersection_Methods)
return(((CSG *)Object)->Inverted);
if (methods == &CSG_Union_Methods)
return(((CSG *)Object)->Inverted);
if (methods == &Disc_Methods)
return(((DISC *)Object)->Inverted);
if (methods == &Ellipsoid_Methods)
return(((SPHERE *)Object)->Inverted);
if (methods == &Height_Field_Methods)
return(((HEIGHT_FIELD *)Object)->Inverted);
if (methods == &Poly_Methods)
return(((POLY *)Object)->Inverted);
if (methods == &Quadric_Methods)
return(((QUADRIC *)Object)->Inverted);
if (methods == &Sphere_Methods)
return(((SPHERE *)Object)->Inverted);
return(FALSE);
}
/*****************************************************************************
*
* FUNCTION : Remove_Unnecessary_Bounds
*
* ARGUMENTS : none
*
* MODIFIED ARGS : none
*
* RETURN VALUE : none
*
* AUTHOR : Dieter Bayer, May 1994
*
* DESCRIPTION
*
* Remove unnecessary bounding objects.
*
* CHANGES
*
* -
*
******************************************************************************/
void Remove_Unnecessary_Bounds()
{
long removed;
OBJECT *Sib;
removed = 0;
fprintf(stderr, "Removing bounds");
Begin_Point();
for (Sib = Frame.Objects; Sib != NULL; Sib = Sib->Sibling)
{
Remove_Bound(Sib, &removed);
}
fprintf(stderr, "(%ld removed)\n", removed);
End_Point();
}
/*****************************************************************************
*
* FUNCTION : Remove_Bound
*
* ARGUMENTS : Object - Object
* removed - Counter to count removed bounding objects
*
* MODIFIED ARGS : removed
*
* RETURN VALUE : none
*
* AUTHOR : Dieter Bayer, May 1994
*
* DESCRIPTION
*
* Remove bounding objects from finite primitive objects. This has to be
* done after (bounded) unions were split.
*
* CHANGES
*
* -
*
******************************************************************************/
static void Remove_Bound(Object, removed)
OBJECT *Object;
long *removed;
{
OBJECT *Sib;
if (Object == NULL)
return;
if (Object->Type & COMPOUND_OBJECT)
{
if (Object->Type & LIGHT_SOURCE_OBJECT)
{
Remove_Bound(((LIGHT_SOURCE *)Object)->Children, removed);
}
else
{
/*
Don't know if this is a good idea ...
Object->Bound = NULL;
*/
for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
{
Remove_Bound(Sib, removed);
}
}
}
else
{
if (Object->Bound != NULL)
{
/* Remove bounding boxes around finite objects.
(it's a waste of time to bound these objects) */
if ((Object->Methods == &Bicubic_Patch_Methods) ||
(Object->Methods == &Box_Methods) ||
(Object->Methods == &Csg_Height_Field_Methods) ||
(Object->Methods == &Cone_Methods) ||
(Object->Methods == &Disc_Methods) ||
(Object->Methods == &Ellipsoid_Methods) ||
(Object->Methods == &Height_Field_Methods) ||
(Object->Methods == &Plane_Methods) ||
(Object->Methods == &Quadric_Methods) ||
(Object->Methods == &Sphere_Methods) ||
(Object->Methods == &Smooth_Triangle_Methods) ||
(Object->Methods == &Triangle_Methods))
{
Object->Bound = NULL;
Print_Point(POINT_MOD);
(*removed)++;
}
}
}
}
/*****************************************************************************
*****************************************************************************/
void Print_Quadric_Stats()
{
/*
This gives wrong results....
if (FoundCone)
fprintf(stderr, "Quadric-Cone found: %ld\n", FoundCone);
if (FoundCylinder)
fprintf(stderr, "Quadric-Cylinder found: %ld\n", FoundCylinder);
if (FoundEllipsoid)
fprintf(stderr, "Quadric-Ellipsoids found: %ld\n", FoundEllipsoid);
*/
}
/*****************************************************************************
*
* FUNCTION : Compute_Quadric_BBox
*
* ARGUMENTS : Quadric - Qaudric object
*
* MODIFIED ARGS : Quadric
*
* RETURN VALUE : none
*
* AUTHOR : Dieter Bayer, May 1994
*
* DESCRIPTION
*
* Compute a bounding box around a quadric.
*
* This function calculates the bounding box for quadrics given in
* their normal form, i.e. f(x,y,z) = A*x*x + B*y*y + C*z*z + J = 0.
* That's the form normally used in the declaration of quadric shapes.
*
* They can still be translated, rotated, and scaled after declaration.
*
* Currently clipped cones, cylinders, and ellipsoids are supported.
*
* (Btw, a quadric ellipsoid is intersected faster than a scaled sphere!!!
* The problem that quadrics don't respond to automatic bounding is
* solved for some quadric shapes with this function. With this function
* the modules for cones/cylinders and ellipsoids may even be obsolete.)
*
*
* CHANGES
*
* -
*
******************************************************************************/
void Compute_Quadric_BBox(Quadric)
QUADRIC *Quadric;
{
DBL kx, ky, kz, k, a, b, c;
DBL rx, ry, rz, rx1, rx2, ry1, ry2, rz1, rz2, x, y, z;
DBL New_Volume, Old_Volume;
VECTOR Min, Max, TmpMin, TmpMax, NewMin, NewMax, ClipMin, ClipMax;
BBOX Old;
OBJECT *Sib;
if (!(Extended_Options & USE_BOUND_QUADRICS))
return;
/* Inverted quadrics are infinite */
/*
That's true ... but it makes no difference in intersecting the quadric ...
it only affects the inside/outside test ...
if (Quadric->Inverted)
return;
*/
/* Check for 'normal' form. If the quadric isn't in it's normal form
we can't do anything (we could, but that would be to tedious!
Diagonalising the quadric's 4x4 matrix, i.e. finding its eigenvalues
and eigenvectors -> solving a 4th order polynom) */
kx = Quadric->Mixed_Terms.x;
ky = Quadric->Mixed_Terms.y;
kz = Quadric->Mixed_Terms.z;
if ((fabs(kx) > EPSILON) || (fabs(ky) > EPSILON) || (fabs(kz) > EPSILON))
return;
kx = Quadric->Terms.x;
ky = Quadric->Terms.y;
kz = Quadric->Terms.z;
if ((fabs(kx) > EPSILON) || (fabs(ky) > EPSILON) || (fabs(kz) > EPSILON))
return;
/* Get old bounding box */
Old = Quadric->Bounds;
/* Init new bounding box */
NewMin.x = NewMin.y = NewMin.z = -BOUND_HUGE;
NewMax.x = NewMax.y = NewMax.z = BOUND_HUGE;
/* Get the bounding box of the clipping object */
ClipMin.x = ClipMin.y = ClipMin.z = -BOUND_HUGE;
ClipMax.x = ClipMax.y = ClipMax.z = BOUND_HUGE;
if (Quadric->Clip != NULL)
{
Min.x = Min.y = Min.z = -BOUND_HUGE;
Max.x = Max.y = Max.z = +BOUND_HUGE;
/* Intersect the members bounding boxes */
for (Sib = Quadric->Clip; Sib != NULL; Sib = Sib->Sibling)
{
if (!Test_Inverted(Sib))
{
if (Sib->Methods == &Plane_Methods)
{
Compute_Plane_Min_Max((PLANE *)Sib, &TmpMin, &TmpMax);
}
else
{
TmpMin.x = Sib->Bounds.Lower_Left.x;
TmpMin.y = Sib->Bounds.Lower_Left.y;
TmpMin.z = Sib->Bounds.Lower_Left.z;
TmpMax.x = Sib->Bounds.Lower_Left.x + Sib->Bounds.Lengths.x;
TmpMax.y = Sib->Bounds.Lower_Left.y + Sib->Bounds.Lengths.y;
TmpMax.z = Sib->Bounds.Lower_Left.z + Sib->Bounds.Lengths.z;
}
Min.x = max(Min.x, TmpMin.x);
Min.y = max(Min.y, TmpMin.y);
Min.z = max(Min.z, TmpMin.z);
Max.x = min(Max.x, TmpMax.x);
Max.y = min(Max.y, TmpMax.y);
Max.z = min(Max.z, TmpMax.z);
}
}
ClipMin = Min;
ClipMax = Max;
}
/* Get coefficients of 'normal' form: kx*x*x + ky*y*y + kz*z*z + k */
kx = Quadric->Square_Terms.x;
ky = Quadric->Square_Terms.y;
kz = Quadric->Square_Terms.z;
k = Quadric->Constant;
/* We want kx to be non-negative */
if (kx < 0.0)
{
kx = -kx;
ky = -ky;
kz = -kz;
k = -k;
}
/*************************************************************
Check for ellipsoid
x*x y*y z*z
----- + ----- + ----- - 1 = 0
a*a b*b c*c
*************************************************************/
if ((kx > 0.0) && (ky > 0.0) && (kz > 0.0) && (k < 0.0))
{
FoundEllipsoid++;
a = sqrt(-k/kx);
b = sqrt(-k/ky);
c = sqrt(-k/kz);
NewMin.x = -a;
NewMin.y = -b;
NewMin.z = -c;
NewMax.x = a;
NewMax.y = b;
NewMax.z = c;
}
/*************************************************************
Check for cylinder (x-axis)
y*y z*z
----- + ----- - 1 = 0
b*b c*c
*************************************************************/
if ((kx == 0.0) && (ky > 0.0) && (kz > 0.0) && (k < 0.0))
{
FoundCylinder++;
b = sqrt(-k/ky);
c = sqrt(-k/kz);
NewMin.y = -b;
NewMin.z = -c;
NewMax.y = b;
NewMax.z = c;
}
/*************************************************************
Check for cylinder (y-axis)
x*x z*z
----- + ----- - 1 = 0
a*a c*c
*************************************************************/
if ((kx > 0.0) && (ky == 0.0) && (kz > 0.0) && (k < 0.0))
{
FoundCylinder++;
a = sqrt(-k/kx);
c = sqrt(-k/kz);
NewMin.x = -a;
NewMin.z = -c;
NewMax.x = a;
NewMax.z = c;
}
/*************************************************************
Check for cylinder (z-axis)
x*x y*y
----- + ----- - 1 = 0
a*a b*b
*************************************************************/
if ((kx > 0.0) && (ky > 0.0) && (kz == 0.0) && (k < 0.0))
{
FoundCylinder++;
a = sqrt(-k/kx);
b = sqrt(-k/ky);
NewMin.x = -a;
NewMin.y = -b;
NewMax.x = a;
NewMax.y = b;
}
/*************************************************************
Check for cone (x-axis)
x*x y*y z*z
----- - ----- - ----- = 0
a*a b*b c*c
*************************************************************/
if ((kx > 0.0) && (ky < 0.0) && (kz < 0.0) && (k == 0.0))
{
FoundCone++;
a = sqrt(1.0/kx);
b = sqrt(-1.0/ky);
c = sqrt(-1.0/kz);
/* Get radii for lower x value */
x = ClipMin.x;
ry1 = fabs(x * b / a);
rz1 = fabs(x * c / a);
/* Get radii for upper x value */
x = ClipMax.x;
ry2 = fabs(x * b / a);
rz2 = fabs(x * c / a);
ry = max(ry1, ry2);
rz = max(rz1, rz2);
NewMin.y = -ry;
NewMin.z = -rz;
NewMax.y = ry;
NewMax.z = rz;
}
/*************************************************************
Check for cone (y-axis)
x*x y*y z*z
----- - ----- + ----- = 0
a*a b*b c*c
*************************************************************/
if ((kx > 0.0) && (ky < 0.0) && (kz > 0.0) && (k == 0.0))
{
FoundCone++;
a = sqrt(1.0/kx);
b = sqrt(-1.0/ky);
c = sqrt(1.0/kz);
/* Get radii for lower y value */
y = ClipMin.y;
rx1 = fabs(y * a / b);
rz1 = fabs(y * c / b);
/* Get radii for upper y value */
y = ClipMax.y;
rx2 = fabs(y * a / b);
rz2 = fabs(y * c / b);
rx = max(rx1, rx2);
rz = max(rz1, rz2);
NewMin.x = -rx;
NewMin.z = -rz;
NewMax.x = rx;
NewMax.z = rz;
}
/*************************************************************
Check for cone (z-axis)
x*x y*y z*z
----- + ----- - ----- = 0
a*a b*b c*c
*************************************************************/
if ((kx > 0.0) && (ky > 0.0) && (kz < 0.0) && (k == 0.0))
{
FoundCone++;
a = sqrt(1.0/kx);
b = sqrt(1.0/ky);
c = sqrt(-1.0/kz);
/* Get radii for lower z value */
z = ClipMin.z;
rx1 = fabs(z * a / c);
ry1 = fabs(z * b / c);
/* Get radii for upper z value */
z = ClipMax.z;
rx2 = fabs(z * a / c);
ry2 = fabs(z * b / c);
rx = max(rx1, rx2);
ry = max(ry1, ry2);
NewMin.x = -rx;
NewMin.y = -ry;
NewMax.x = rx;
NewMax.y = ry;
}
/* Intersect clipping object's and quadric's bounding boxes */
if (Quadric->Clip != NULL)
{
Min.x = max(NewMin.x, ClipMin.x);
Min.y = max(NewMin.y, ClipMin.y);
Min.z = max(NewMin.z, ClipMin.z);
Max.x = min(NewMax.x, ClipMax.x);
Max.y = min(NewMax.y, ClipMax.y);
Max.z = min(NewMax.z, ClipMax.z);
NewMin = Min;
NewMax = Max;
}
/* Use old or new bounding box? */
New_Volume = (NewMax.x - NewMin.x) *
(NewMax.y - NewMin.y) *
(NewMax.z - NewMin.z);
BOUNDS_VOLUME(Old_Volume, Old);
if (New_Volume < Old_Volume)
{
Quadric->Bounds.Lower_Left = NewMin;
VSub (Quadric->Bounds.Lengths, NewMax, NewMin);
/* Beware of lengths too large */
if (Quadric->Bounds.Lengths.x > CRITICAL_LENGTH)
{
Quadric->Bounds.Lower_Left.x = -BOUND_HUGE/2;
Quadric->Bounds.Lengths.x = BOUND_HUGE;
}
if (Quadric->Bounds.Lengths.y > CRITICAL_LENGTH)
{
Quadric->Bounds.Lower_Left.y = -BOUND_HUGE/2;
Quadric->Bounds.Lengths.y = BOUND_HUGE;
}
if (Quadric->Bounds.Lengths.z > CRITICAL_LENGTH)
{
Quadric->Bounds.Lower_Left.z = -BOUND_HUGE/2;
Quadric->Bounds.Lengths.z = BOUND_HUGE;
}
}
}
/*****************************************************************************
*
* FUNCTION : Compute_Plane_Min_Max
*
* ARGUMENTS : Plane - Plane
* Min, Max - Vectors containing plane's dimensions
*
* MODIFIED ARGS : Min, Max
*
* RETURN VALUE : none
*
* AUTHOR : Dieter Bayer, May 1994
*
* DESCRIPTION
*
* Compute min/max vectors for planes perpendicular to an axis.
*
* CHANGES
*
* -
*
******************************************************************************/
void Compute_Plane_Min_Max(Plane, Min, Max)
PLANE *Plane;
VECTOR *Min, *Max;
{
DBL d;
VECTOR N;
N = Plane->Normal_Vector;
d = -Plane->Distance;
Min->x = Min->y = Min->z = -BOUND_HUGE/2;
Max->x = Max->y = Max->z = BOUND_HUGE/2;
/* y-z-plane */
if (fabs(1.0 - fabs(N.x)) < EPSILON)
{
if (N.x > 0.0)
{
Max->x = d;
}
else
{
Min->x = -d;
}
}
/* x-z-plane */
if (fabs(1.0 - fabs(N.y)) < EPSILON)
{
if (N.y > 0.0)
{
Max->y = d;
}
else
{
Min->y = -d;
}
}
/* x-y-plane */
if (fabs(1.0 - fabs(N.z)) < EPSILON)
{
if (N.z > 0.0)
{
Max->z = d;
}
else
{
Min->z = -d;
}
}
}
#endif